//-----------------------------------------------------------------------
// <copyright file="ExportMsi.cs" company="Achmea">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
//-----------------------------------------------------------------------
namespace Microsoft.Sdc.Tasks.BizTalk2006.Application
{
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;
    using Microsoft.BizTalk.ApplicationDeployment;
    using Microsoft.BizTalk.ExplorerOM;
    using Microsoft.Build.Framework;
    using Microsoft.Sdc.Tasks.BizTalk2004;

    /// <summary>
    /// Exports the BizTalk application to an MSI file.
    /// </summary>
    /// <remarks>
    /// <code>
    /// <![CDATA[<BizTalk2006.Application.ExportMsi Application="EAIApplication" Destiation="C:\Output\EAIApplication.msi" GlobalParties="True" Server="server" Database="database" />]]>
    /// </code>
    /// <para>where:</para>
    /// <para><i>Application (Required)</i></para>
    /// <para>
    /// The BizTalk application to be exported.
    /// </para>
    /// <para><i>Destination (Required)</i></para>
    /// <para>
    /// The destination folder and file of the MSI.
    /// </para>
    /// <para><i>GlobalParties</i></para>
    /// <para>
    /// True of False for exporting all global parties.
    /// </para>
    /// <para><i>server</i></para>
    /// <para>
    /// The logical name of the server hosting the BizTalk management database. If neither this nor the
    /// database name are specified then the installation will default to the local installation.
    /// </para>
    /// <para><i>database</i></para>
    /// <para>
    /// The name of the BizTalk management database. If neither this nor the server name are specified 
    /// then the installation will default to the local installation.
    /// </para>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <Target Name="Test" >
    ///         <!-- Export bindings using the application name -->
    ///         <BizTalk2006.Application.ExportMsi
    ///             Application="EAIApplication"
    ///             Destination="C:\Output\EAIAppliation.msi"
    ///             GlobalParties="True"
    ///             Server="." 
    ///             Database="BizTalkMgmtDb" />
    ///     </Target>
    /// </Project>
    /// ]]></code>    
    /// </example>
    public class ExportMsi : BizTalk2004TaskBase
    {
        #region Private members
        private string application;
        private string destination;
        private bool globalParties;
        #endregion

        /// <summary>
        /// Gets or sets the application.
        /// </summary>
        /// <value>The application.</value>
        [Required]
        public string Application
        {
            get { return this.application; }
            set { this.application = value; }
        }

        /// <summary>
        /// Gets or sets the destination location and msi file of the exported application
        /// </summary>
        /// <value>The location and msi file</value>
        [Required]
        public string Destination
        {
            get { return this.destination; }
            set { this.destination = value; }
        }

        /// <summary>
        /// Gets or sets to export global parties
        /// </summary>
        /// <value>
        /// <b>true</b> to export the global parties, or <b>false</b> otherwise. The default is
        /// <b>false</b>.
        /// </value>
        public bool GlobalParties
        {
            get { return this.globalParties; }
            set { this.globalParties = value; }
        }

        /// <summary>
        /// This is the main execute method that all tasks should implement
        /// </summary>
        /// <remarks>
        /// TaskException should be thrown in the event of errors
        /// </remarks>
        protected override void InternalExecute()
        {
            using (BtsCatalogExplorer explorer = this.GetBtsCatalogExplorer(this.Server, this.Database))
            {
                using (Group group = new Group())
                {
                    group.DBName = this.Database;
                    group.DBServer = this.Server;

                    Microsoft.BizTalk.ApplicationDeployment.ApplicationCollection apps = group.Applications;
                    apps.UiLevel = 2;

                    Microsoft.BizTalk.ApplicationDeployment.Application app = apps[this.Application];
                    List<Resource> exportedResources = new List<Resource>();

                    // Define a variable to check if a resource must have a globalparty property set
                    string applicationLuid = "Application/" + this.Application;

                    Log.LogMessage(string.Format(CultureInfo.InvariantCulture, "Looking for Resources to be exported from Application {0}", this.Application));
                    
                    // Looking for all resource that are in the application, but not defined as a System assembly
                    foreach (Resource resource in app.ResourceCollection)
                    {
                        // Only add non system resources
                        // If so, no adding to the resource list
                        if (!resource.Properties.ContainsKey("IsSystem") || !((bool)resource.Properties["IsSystem"]))
                        {
                            // Check if the resource is part of the globalparties.
                            if (this.GlobalParties && 
                                resource.Luid.Equals(applicationLuid, System.StringComparison.InvariantCultureIgnoreCase))
                            {
                                Log.LogMessage(string.Format(CultureInfo.InvariantCulture, "Application {0} will include GlobalParties: {1}", this.Application, this.GlobalParties));
                                resource.Properties["IncludeGlobalPartyBinding"] = this.GlobalParties;
                            }

                            // Add the resource to the resourceList
                            Log.LogMessage(string.Format(CultureInfo.InvariantCulture, "Exporting Resource {0} from Application {1}", resource.Luid, this.Application));
                            exportedResources.Add(resource);
                        }
                    }

                    // Check if the Path of the Destination really exists, or else create it
                    if (!Directory.Exists(Path.GetDirectoryName(this.Destination)))
                    {
                        Log.LogMessage(string.Format(CultureInfo.InvariantCulture, "Create destination directory: {0}", Path.GetDirectoryName(this.Destination)));
                        Directory.CreateDirectory(Path.GetDirectoryName(this.Destination));
                    }

                    // Check if the file has an extension? If not add the .xml extension.
                    if (!Path.HasExtension(this.Destination))
                    {
                        this.Destination = Path.ChangeExtension(this.Destination, ".msi");
                    }

                    Log.LogMessage(string.Format(CultureInfo.InvariantCulture, "Exporting Application {0} to destination {1}", this.Application, this.Destination));
                    app.Export(this.Destination, exportedResources, null);
                }
            }
        }
    }
}
